package com.cloud.note.service.impl;

import com.cloud.note.dto.attachment.AttachmentResponse;
import com.cloud.note.dto.note.BatchOperationRequest;
import com.cloud.note.dto.note.CreateNoteRequest;
import com.cloud.note.dto.note.NoteResponse;
import com.cloud.note.dto.note.UpdateNoteRequest;
import com.cloud.note.dto.tag.TagResponse;
import com.cloud.note.model.Attachment;
import com.cloud.note.model.Note;
import com.cloud.note.model.Tag;
import com.cloud.note.model.constant.NoteOperationType;
import com.cloud.note.repository.AttachmentRepository;
import com.cloud.note.repository.NoteRepository;
import com.cloud.note.repository.TagRepository;
import com.cloud.note.service.NoteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class NoteServiceImpl implements NoteService {

    @Autowired
    private NoteRepository noteRepository;

    @Autowired
    private TagRepository tagRepository;

    @Autowired
    private AttachmentRepository attachmentRepository;

    @Override
    public Page<NoteResponse> getAllNotes(String userId, Pageable pageable, String filter, String tagId,
            String keyword) {
        Page<Note> notePage;

        // 根据筛选条件获取笔记
        if (filter != null) {
            switch (filter) {
                case "starred":
                    notePage = noteRepository.findByUserIdAndIsStarredTrueAndIsTrashedFalse(userId, pageable);
                    break;
                case "archived":
                    notePage = noteRepository.findByUserIdAndIsArchivedTrueAndIsTrashedFalse(userId, pageable);
                    break;
                case "trashed":
                    notePage = noteRepository.findByUserIdAndIsTrashedTrue(userId, pageable);
                    break;
                default:
                    notePage = noteRepository.findByUserIdAndIsTrashedFalse(userId, pageable);
                    break;
            }
        } else if (tagId != null) {
            // 按标签筛选
            notePage = noteRepository.findByUserIdAndTagId(userId, tagId, pageable);
        } else if (keyword != null && !keyword.trim().isEmpty()) {
            // 按关键字搜索
            notePage = noteRepository.searchByKeyword(userId, keyword, pageable);
        } else {
            // 获取所有非删除的笔记
            notePage = noteRepository.findByUserIdAndIsTrashedFalse(userId, pageable);
        }

        // 转换为DTO
        return notePage.map(this::convertToNoteResponse);
    }

    @Override
    public NoteResponse getNoteById(String userId, String noteId) {
        Note note = noteRepository.findByIdAndUserId(noteId, userId)
                .orElseThrow(() -> new RuntimeException("笔记不存在"));

        return convertToNoteResponse(note);
    }

    @Override
    @Transactional
    public NoteResponse createNote(String userId, CreateNoteRequest createNoteRequest) {
        Note note = new Note();
        note.setId(UUID.randomUUID().toString());
        note.setUserId(userId);
        note.setTitle(createNoteRequest.getTitle());
        note.setContent(createNoteRequest.getContent());
        note.setColor(createNoteRequest.getColor());
        note.setSynced(false);
        note.setStarred(false);
        note.setArchived(false);
        note.setTrashed(false);
        note.setReminder(createNoteRequest.isReminder());
        note.setReminderDate(createNoteRequest.getReminderDate());
        note.setCategory(createNoteRequest.getCategory());
        note.setCreatedAt(LocalDateTime.now());
        note.setUpdatedAt(LocalDateTime.now());

        // 添加标签
        if (createNoteRequest.getTags() != null && !createNoteRequest.getTags().isEmpty()) {
            Set<Tag> tags = getOrCreateTags(userId, createNoteRequest.getTags());
            note.setTags(tags);
        }

        noteRepository.save(note);

        return convertToNoteResponse(note);
    }

    @Override
    @Transactional
    public NoteResponse updateNote(String userId, String noteId, UpdateNoteRequest updateNoteRequest) {
        Note note = noteRepository.findByIdAndUserId(noteId, userId)
                .orElseThrow(() -> new RuntimeException("笔记不存在"));

        if (updateNoteRequest.getTitle() != null) {
            note.setTitle(updateNoteRequest.getTitle());
        }

        if (updateNoteRequest.getContent() != null) {
            note.setContent(updateNoteRequest.getContent());
        }

        if (updateNoteRequest.getColor() != null) {
            note.setColor(updateNoteRequest.getColor());
        }

        note.setReminder(updateNoteRequest.isReminder());
        note.setReminderDate(updateNoteRequest.getReminderDate());

        if (updateNoteRequest.getCategory() != null) {
            note.setCategory(updateNoteRequest.getCategory());
        }

        note.setSynced(false);
        note.setUpdatedAt(LocalDateTime.now());

        // 更新标签
        if (updateNoteRequest.getTags() != null) {
            Set<Tag> tags = getOrCreateTags(userId, updateNoteRequest.getTags());
            note.setTags(tags);
        }

        noteRepository.save(note);

        return convertToNoteResponse(note);
    }

    @Override
    @Transactional
    public void moveToTrash(String userId, String noteId) {
        Note note = noteRepository.findByIdAndUserId(noteId, userId)
                .orElseThrow(() -> new RuntimeException("笔记不存在"));

        note.setTrashed(true);
        note.setSynced(false);
        note.setUpdatedAt(LocalDateTime.now());

        noteRepository.save(note);
    }

    @Override
    @Transactional
    public void restoreFromTrash(String userId, String noteId) {
        Note note = noteRepository.findByIdAndUserId(noteId, userId)
                .orElseThrow(() -> new RuntimeException("笔记不存在"));

        note.setTrashed(false);
        note.setSynced(false);
        note.setUpdatedAt(LocalDateTime.now());

        noteRepository.save(note);
    }

    @Override
    @Transactional
    public void deleteNote(String userId, String noteId) {
        Note note = noteRepository.findByIdAndUserId(noteId, userId)
                .orElseThrow(() -> new RuntimeException("笔记不存在"));

        // 删除笔记
        noteRepository.delete(note);
    }

    @Override
    @Transactional
    public void batchOperation(String userId, BatchOperationRequest batchOperationRequest) {
        List<Note> notes = noteRepository.findByIdInAndUserId(batchOperationRequest.getNoteIds(), userId);

        if (notes.isEmpty()) {
            return;
        }

        NoteOperationType operationType = NoteOperationType.valueOf(batchOperationRequest.getOperation().toUpperCase());

        for (Note note : notes) {
            switch (operationType) {
                case TRASH:
                    note.setTrashed(true);
                    break;
                case RESTORE:
                    note.setTrashed(false);
                    break;
                case STAR:
                    note.setStarred(true);
                    break;
                case UNSTAR:
                    note.setStarred(false);
                    break;
                case ARCHIVE:
                    note.setArchived(true);
                    break;
                case UNARCHIVE:
                    note.setArchived(false);
                    break;
                case DELETE:
                    noteRepository.delete(note);
                    continue;
            }

            note.setSynced(false);
            note.setUpdatedAt(LocalDateTime.now());
            noteRepository.save(note);
        }
    }

    private Set<Tag> getOrCreateTags(String userId, List<String> tagNames) {
        Set<Tag> tags = new HashSet<>();

        for (String tagName : tagNames) {
            if (tagName == null || tagName.trim().isEmpty()) {
                continue;
            }

            // 先尝试查找现有标签
            Optional<Tag> existingTag = tagRepository.findByUserIdAndName(userId, tagName.trim());

            if (existingTag.isPresent()) {
                tags.add(existingTag.get());
            } else {
                // 创建新标签
                Tag newTag = new Tag();
                newTag.setId(UUID.randomUUID().toString());
                newTag.setUserId(userId);
                newTag.setName(tagName.trim());
                newTag.setColor("#" + Integer.toHexString((new Random().nextInt(0xFFFFFF) + 1)));
                newTag.setCreatedAt(LocalDateTime.now());

                tagRepository.save(newTag);
                tags.add(newTag);
            }
        }

        return tags;
    }

    private NoteResponse convertToNoteResponse(Note note) {
        // 转换标签
        List<TagResponse> tagResponses = note.getTags().stream()
                .map(tag -> TagResponse.builder()
                        .id(tag.getId())
                        .name(tag.getName())
                        .color(tag.getColor())
                        .noteCount(null) // 这里不需要统计笔记数量
                        .createdAt(tag.getCreatedAt())
                        .build())
                .collect(Collectors.toList());

        // 获取附件
        List<Attachment> attachments = attachmentRepository.findByNoteId(note.getId());

        // 转换附件
        List<AttachmentResponse> attachmentResponses = attachments.stream()
                .map(attachment -> AttachmentResponse.builder()
                        .id(attachment.getId())
                        .name(attachment.getName())
                        .type(attachment.getType())
                        .uri(attachment.getUri())
                        .size(attachment.getSize())
                        .isSynced(attachment.isSynced())
                        .createdAt(attachment.getCreatedAt())
                        .build())
                .collect(Collectors.toList());

        return NoteResponse.builder()
                .id(note.getId())
                .title(note.getTitle())
                .content(note.getContent())
                .createdAt(note.getCreatedAt())
                .updatedAt(note.getUpdatedAt())
                .color(note.getColor())
                .isSynced(note.isSynced())
                .lastSyncedAt(note.getLastSyncedAt())
                .tags(tagResponses)
                .isStarred(note.isStarred())
                .isArchived(note.isArchived())
                .isTrashed(note.isTrashed())
                .isReminder(note.isReminder())
                .reminderDate(note.getReminderDate())
                .category(note.getCategory())
                .attachments(attachmentResponses)
                .build();
    }
}